/**
 * 
 */
package com.gopay.cashier.aspect;

import java.io.IOException;
import java.net.InetSocketAddress;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import com.gopay.cashier.web.controller.CashierBackNotifyController;
import com.gopay.cashier.web.controller.CashierFrontNotifyController;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.log4j.Logger;
import org.apache.mina.core.future.CloseFuture;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.service.IoConnector;
import org.aspectj.lang.JoinPoint;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.util.WebUtils;


import com.gopay.cashier.web.command.BankPayCallbackCommand;
import com.gopay.common.constants.logging.BusinessLogType;
import com.gopay.common.constants.logging.BussinessLogInfo;
import com.gopay.common.constants.logging.SendType;
import com.gopay.common.constants.logging.VoType;
import com.gopay.common.constants.trans.TxnStaCode;
import com.gopay.common.cps.dao.order.CpsGeneralMainOrderQueryDAO;
import com.gopay.common.cps.manager.order.FullCpsGenRecvOrderQueryManager;
import com.gopay.common.domain.cps.CpsGenMainOrder;
import com.gopay.common.domain.logging.business.BaseBusinessLog;
import com.gopay.common.domain.send.SendMessage;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.JsonUtils;
import com.gopay.common.util.RequestUtils;

/**
 * @BankRevRefLogAspect.java
 * @author Ryan
 * @2013-8-23 下午3:06:28 www.gopay.com.cn Inc.All rights reserved.
 */
public class BankRevRefLogAspect {

    private static final Logger logger = Logger.getLogger(BankRevRefLogAspect.class);
    private String ip;
    private int port;

    @Autowired
    protected FullCpsGenRecvOrderQueryManager fullCpsGenRecvOrderQueryManager;
    
    @Resource(name="cpsGeneralMainOrderQueryDAO")
    private CpsGeneralMainOrderQueryDAO cpsGeneralMainOrderQueryDAO;

    private HttpServletRequest request;

    @Resource(name = "nioSocketConnector")
    private IoConnector nioSocketConnector;

    public void process(JoinPoint jp) {

        Object target = jp.getTarget();

        String method = jp.getSignature().getName();

        Object[] args = jp.getArgs();

        try {
            if (target instanceof CashierBackNotifyController) {

                // 日志传输对象
                BaseBusinessLog merLog = new BaseBusinessLog();
                //时间(YYYYMMDHHMISSFFF)|系统号|操作行为|商户订单号|商户号|银行编号|银行信息 
                if ("execute".equals(method)) {
                    // 取第三个参数
                    BankPayCallbackCommand command = (BankPayCallbackCommand) args[2];
                   
                    CpsGenMainOrder order = fullCpsGenRecvOrderQueryManager.findByGopayOrderId(command.getOrderId());
                    merLog.setSysId("cashier");

                    // get the fields from form
                    merLog.setBusinessType(BussinessLogInfo.getName(BusinessLogType.RCV_BANK_MSG.value));

                    // 商户号
                    merLog.setCusId(order.getMerId());

                    // 商户订单
                    merLog.setOrderId(order.getGopayOrderId());

                    if (request != null) {
                        merLog.setReqIp(RequestUtils.getRemoteRealIpAddr(request));
                        merLog.setSendUri(request.getHeader("Referer"));
                    }

                    StringBuffer sb = new StringBuffer();

                    sb.append(DateUtils.getCurrDate()).append("|");

                    sb.append(merLog.getSysId()).append("|");

                    sb.append(BussinessLogInfo.getName(BusinessLogType.RCV_BANK_MSG.value)).append("|");

                    sb.append(merLog.getOrderId()).append("|");

                    sb.append(merLog.getCusId()).append("|");

                    sb.append(order.getOutStlmId()).append("|");

                    sb.append(ToStringBuilder.reflectionToString(command));

                    if (TxnStaCode.TXN_STA_CD_30102.value == order.getTxnStaCd() || TxnStaCode.TXN_STA_CD_20000.value ==order.getTxnStaCd()) {
                        sb.append("通过");
                    } else {
                        sb.append("未通过");
                    }

                    merLog.setData(sb.toString());

                    sendLogMsg(merLog);
                }
            }
        } catch (Throwable e) {
            logger.error(e);
        }
    }

    public void processFront(JoinPoint jp) {
        Object target = jp.getTarget();

        String method = jp.getSignature().getName();

        Object[] args = jp.getArgs();

        try {
            if (target instanceof CashierFrontNotifyController) {

                // 日志传输对象
                BaseBusinessLog merLog = new BaseBusinessLog();
                //时间(YYYYMMDHHMISSFFF)|系统号|操作行为|商户订单号|商户号|银行编号|银行信息 
                if ("execute".equals(method)) {
                    // 取第三个参数
                    HttpServletRequest request =(HttpServletRequest)args[0];
                    
                    String orderId = WebUtils.findParameterValue(request, "orderId");
                    
                    CpsGenMainOrder order = cpsGeneralMainOrderQueryDAO.find(CpsGenMainOrder.class, orderId);
                    merLog.setSysId("cashier");

                    // get the fields from form
                    merLog.setBusinessType(BussinessLogInfo.getName(BusinessLogType.RCV_BANK_MSG.value));

                    // 商户号
                    merLog.setCusId(order.getMerId());

                    // 商户订单
                    merLog.setOrderId(order.getGopayOrderId());

                    merLog.setReqIp(RequestUtils.getRemoteRealIpAddr(request));

                    if (request != null) {
                        merLog.setSendUri(request.getHeader("Referer"));
                    }

                    StringBuffer sb = new StringBuffer();

                    sb.append(DateUtils.getCurrDate()).append("|");

                    sb.append(merLog.getSysId()).append("|");

                    sb.append(BussinessLogInfo.getName(BusinessLogType.RCV_BANK_MSG.value)).append("|");

                    sb.append(merLog.getOrderId()).append("|");

                    sb.append(merLog.getCusId()).append("|");

                    sb.append(order.getOutStlmId()).append("|");

                    sb.append( WebUtils.findParameterValue(request, "orderId"));

                    if (TxnStaCode.TXN_STA_CD_30101.value == (order.getTxnStaCd())) {

                        sb.append("通过");
                    } else {

                        sb.append("未通过");
                    }

                    merLog.setData(sb.toString());

                    sendLogMsg(merLog);
                }
            }
        } catch (Throwable e) {
            logger.error(e);
        }

    }

    private void sendLogMsg(BaseBusinessLog mlog) throws Throwable {

        String data = "";
        try {
            data = JsonUtils.toJson(mlog);
            logger.error("message : " + data);
        } catch (JsonGenerationException e1) {
            logger.error("", e1);
        } catch (JsonMappingException e1) {
            logger.error("", e1);
        } catch (IOException e1) {
            logger.error("", e1);
        }

        // 打印日志
        logger.error(data);
        SendMessage msg = SendMessage.getSendMessage();
        msg.setSendType(SendType.LOG);
        msg.setVoType(VoType.MER_BUSSINESS);
        msg.setData(data);

        ConnectFuture future = nioSocketConnector.connect(new InetSocketAddress(ip, port));
        // 同步调用
        future.awaitUninterruptibly();
        WriteFuture  writeFuture = future.getSession().write(msg.toString());
        writeFuture.awaitUninterruptibly();
        future.getSession().close(true);
    }

    /**
     * @return the ip
     */
    public String getIp() {
        return ip;
    }

    /**
     * @param ip
     *            the ip to set
     */
    public void setIp(String ip) {
        this.ip = ip;
    }

    /**
     * @return the port
     */
    public int getPort() {
        return port;
    }

    /**
     * @param port
     *            the port to set
     */
    public void setPort(int port) {
        this.port = port;
    }

    /**
     * @return the request
     */
    public HttpServletRequest getRequest() {
        return request;
    }

    /**
     * @param request
     *            the request to set
     */
    public void setRequest(HttpServletRequest request) {
        this.request = request;
    }

    /**
     * @return the nioSocketConnector
     */
    public IoConnector getNioSocketConnector() {
        return nioSocketConnector;
    }

    /**
     * @param nioSocketConnector
     *            the nioSocketConnector to set
     */
    public void setNioSocketConnector(IoConnector nioSocketConnector) {
        this.nioSocketConnector = nioSocketConnector;
    }

}
